﻿#include "GY_TreeView.h"
#include <QMessageBox>
#include <QTableWidgetItem>
#include <QTime>
#include <QMap>
#include <QVector>
#include <QModelIndex>
#include <QMouseEvent>

GY_TreeView::GY_TreeView(QWidget *parent)
    : QTreeView(parent)
{
    m_pModel = new QStandardItemModel(this);
    setSelectionBehavior(QAbstractItemView::SelectRows);//一次选择一行
    setSelectionMode(QAbstractItemView::SingleSelection); //设置选择模式，选择单行
    setSelectionMode(QAbstractItemView::ExtendedSelection); //设置选择模式，设置可多选
    connect(this,&GY_TreeView::clicked,this,&GY_TreeView::receiveClicked); //单击接收事件

}

/**
 * @brief setColumnCount 设置列数
 * @param columnCount 添加的列数
 */
void GY_TreeView::setColumnCount(const int columnCount)
{
    if(columnCount<=0) //设置0列及以下为无效
    {
        return;
    }
    if( !m_pModel ){ //如果列表为空

        m_pModel->setColumnCount(columnCount);
        QStringList headNames; //创建表名
        for(int i=0; i<columnCount;i++)
        {
            headNames << QString("标题%1").arg(i+1);
        }
        m_pModel->setHorizontalHeaderLabels(headNames); //将表名导入列表中
        this->setModel(m_pModel); //添加m_pModel到treeview中
    }
    else //如果列表存在数据
    {
        QStandardItemModel *pNewModel = new QStandardItemModel(this); //创建一个新的model指针
        pNewModel->setColumnCount(columnCount);
        //设置已有列名
        QStringList headNames;
        for(int i=0;i<columnCount;i++)
        {
            if(i<m_pModel->columnCount())
            {
                headNames<<m_pModel->horizontalHeaderItem(i)->text();
            }
            else
            {
                headNames<<QString("标题%1").arg(i+1);
            }
        }
        pNewModel->setHorizontalHeaderLabels(headNames); //将列名导入列表中

        //设置已有数据
        for(int i=0;i<m_pModel->rowCount();i++)
        {
            QList<QStandardItem*> rowItems;
            QVariant rowId;
            for(int j=0;j<columnCount;j++)
            {
                //设置
                QStandardItem* pNewRowItem = new QStandardItem;
                //判定设置的列数是否少于原列数
                if(j<m_pModel->columnCount())
                {
                    QStandardItem* pOldRowItem = m_pModel->item(i,j);
                    pNewRowItem->setData(pOldRowItem->data());
                    pNewRowItem->setText(pOldRowItem->text()); //后期添加按键，则不能用text格式，需判断一下
                    if(j==0)
                    {
                        rowId=pOldRowItem->data(Qt::UserRole);
                        pNewRowItem->setData(rowId,Qt::UserRole);
                        pNewRowItem->setIcon(m_IconIdMap.value(rowId));
                    }
                }
                else
                {
                    m_TreeNodeInfo.value(rowId)->nodeDatas.append(QVariant());
                }
                rowItems<< pNewRowItem; //将新行数据依次传入list容器中
            }
            if(rowItems.size()>0)
            {
                //更改存储的节点信息
                if(m_TreeNodeInfo.contains(rowId))
                {
                    m_TreeNodeInfo.value(rowId)->pNodeItem=rowItems[0]; //将rowid设为父节点
                    //移除多余数据
                    for(int k=rowItems.size();k<m_TreeNodeInfo.value(rowId)->nodeDatas.size();k++)
                    {
                         m_TreeNodeInfo.value(rowId)->nodeDatas.removeLast();
                    }
                }

                //递归挂接下一级节点
                QStandardItem* pTempItem = m_pModel->item(i);
                if(pTempItem->hasChildren())
                {
                    moveItems(rowItems[0],pTempItem,pNewModel->columnCount());
                }
            }
            pNewModel->appendRow(rowItems);
        }
        this->setModel(pNewModel);
        delete m_pModel;
        m_pModel = pNewModel;
    }
}

/**
 * @brief moveItems 将旧列表items赋给新列表
 * @param pDetItem 目的item
 * @param pSrcItem 源item
 * @param columnCount 目的列表列数
 */
void GY_TreeView::moveItems(QStandardItem* const pDetItem, const QStandardItem *pSrcItem,const int columnCount)
{
    for(int i=0;i<pSrcItem->rowCount();i++)
    {
        QList<QStandardItem*> rowItems;
        QVariant rowId;
        for(int j=0;j<columnCount;j++)
        {
            QStandardItem* pNewRowItem = new QStandardItem;
            if(j<m_pModel->columnCount())
            {
                QStandardItem* pOldRowItem = pSrcItem->child(i,j);
                pNewRowItem->setData(pOldRowItem->data());
                pNewRowItem->setText(pOldRowItem->text());
                if(j==0)
                {
                    rowId=pOldRowItem->data(Qt::UserRole);
                    pNewRowItem->setData(pOldRowItem->data(Qt::UserRole),Qt::UserRole);
                    pNewRowItem->setIcon(m_IconIdMap.value(rowId));
                }
            }
            rowItems<<pNewRowItem;
        }
        if(rowItems.size()>0)
        {
            //更改存储的节点信息
            if(m_TreeNodeInfo.contains(rowId))
            {
                m_TreeNodeInfo.value(rowId)->pNodeItem=rowItems[0];
                //移除多余数据
                for(int k=rowItems.size();k<m_TreeNodeInfo.value(rowId)->nodeDatas.size();k++)
                {
                    m_TreeNodeInfo.value(rowId)->nodeDatas.removeLast();
                }
            }
            //递归挂接下一级节点
            QStandardItem* pTempItem = pSrcItem->child(i);
            if(pTempItem->hasChildren())
            {
                moveItems(rowItems[0],pTempItem,columnCount);
            }
        }
        pDetItem->appendRow(rowItems);
    }
}

/**
 * @brief addColumn 添加列数
 * @param columnName 添加的列名
 */
void GY_TreeView::addColumn(const QString &columnName)
{
    if(columnName==nullptr) //设置列名为空无效
    {
        return;
    }
    int column = m_pModel->columnCount();
    setColumnCount(column+1);
    QStandardItem* pItem = new QStandardItem(columnName);
    m_pModel->setHorizontalHeaderItem(column,pItem); //将添加的列名放在列表后
}

/**
 * @brief insterColumn 插入列
 * @param index 插入在第几列
 * @param columnName 插入的列名
 * @return 返回插入列是否成功
 */
bool GY_TreeView::insterColumn(const int index, const QString &columnName)
{
    if(!m_pModel || index<0 || index>m_pModel->columnCount()){
        return false;
    }
    else
    {
        QList<QStandardItem*> listItem;
        for(int i=0;i<m_pModel->rowCount();i++)
        {
            QStandardItem* pRowItem = m_pModel->item(i);
            QVariant rowId = itemFindId(pRowItem); //找到对应的id号
            m_TreeNodeInfo.value(rowId)->nodeDatas.insert(index,QVariant()); //更新map数据表
            if(m_pModel->hasChildren())
            {
                insertChildColumn(index,pRowItem);
            }
            listItem<<pRowItem;
        }
        m_pModel->insertColumn(index,listItem);
        QStandardItem* pitem = new QStandardItem(columnName);
        m_pModel->setHorizontalHeaderItem(index,pitem);
        this->setModel(m_pModel);
        return true;
    }
}

/**
 * @brief insertChildColumn 循环插入空白列
 * @param pItem 每行的item
 */
void GY_TreeView::insertChildColumn(const int index, QStandardItem * const pItem)
{
    if(!pItem)
    {
        return;
    }
    QList<QStandardItem*> listItems;
    pItem->insertColumn(index,listItems);
    for(int i=0;i<pItem->columnCount();i++)
    {
        QStandardItem* pChildItem = pItem->child(i);
        QVariant rowId = itemFindId(pChildItem);
        m_TreeNodeInfo.value(rowId)->nodeDatas.insert(index,QVariant());
        listItems<<pChildItem;
        insertChildColumn(index,pChildItem);
    }
}

/**
 * @brief deleteColumn 删除列
 * @param index 删除的第几列
 * @return 返回删除列是否成功
 */
bool GY_TreeView::deleteColumn(const int index)
{
    if(m_pModel==nullptr ||index<0 || index>m_pModel->columnCount())
    {
        return false;
    }
    QStandardItem *pitem = m_pModel->invisibleRootItem();
    pitem->takeColumn(index);
    for(int i=0;i<m_pModel->rowCount();i++)
    {
        QStandardItem* pRowItem = m_pModel->item(i);
        QVariant rowId = itemFindId(pRowItem); //找到对应的id号
        m_TreeNodeInfo.value(rowId)->nodeDatas.removeAt(index); //更新map数据表
        if(m_pModel->hasChildren())
        {
            deleteChildColumn(index,pRowItem);
        }
    }
    this->setModel(m_pModel);
    return true;
}

/**
 * @brief deleteChildColumn  循环删除指定列
 * @param index  索引删除第几列
 * @param pItem  每行对应的item
 */
void GY_TreeView::deleteChildColumn(const int index, QStandardItem * const pItem)
{
    if(!pItem)
    {
        return;
    }
    pItem->takeColumn(index);
    for(int i=0;i<pItem->columnCount();i++)
    {
        QStandardItem* pChildItem = pItem->child(i);
        QVariant rowId = itemFindId(pChildItem);
        m_TreeNodeInfo.value(rowId)->nodeDatas.removeAt(index); //更新map数据表
        deleteChildColumn(index,pChildItem);
    }
}

/**
 * @brief setColumnHeadName  修改列名
 * @param nameList  要修改的列名集
 */
void GY_TreeView::setColumnHeadName(const QStringList &nameList)
{
    if(nameList.size()<0)
    {
        return;
    }
    QStringList headNames;
    for(int i=0;i<m_pModel->columnCount();i++)
    {
        if(i<nameList.size())
        {
            headNames<< nameList.at(i);
        }
        else
        {
            headNames<< m_pModel->horizontalHeaderItem(i)->text();
        }
    }
    m_pModel->setHorizontalHeaderLabels(headNames); //将列名导入列表中
}

/**
 * @brief setColumnHeadName  修改某一列列名
 * @param index  要修改名字在第几列
 * @param headName  要修改成的名字
 */
void GY_TreeView::setColumnHeadName(const int index, const QString &headName)
{
    QStandardItem* pitem = new QStandardItem(headName);
    m_pModel->setHorizontalHeaderItem(index,pitem);
}

/**
 * @brief addRowData  添加行数据
 * @param id 行Id
 * @param rowData 行数据
 * @param nodeParentId 父级Id
 * @param iconType 设置图标类型
 * @return 返回添加是否成功
 */
bool GY_TreeView::addRowData(const QVariant &rowId, const QVector<QVariant> &rowData, const QVariant &parentId, const QVariant iconType)
{
    if(m_TreeNodeInfo.contains(rowId)||!rowData.size()||!m_pModel||!m_pModel->columnCount())
    {
        return false;
    }
    QList<QStandardItem*> rowItems;
    for(int i=0;i<m_pModel->columnCount();i++)
    {
        QStandardItem* pItem=new QStandardItem;
        if(i<rowData.size()) //如果插入的行数据的数量大于列数
        {
            pItem->setData(rowData[i]);
            //对每行第一列数据设置id和子节点
            if(i==0)
            {
                pItem->setData(rowId,Qt::UserRole);
                Tree_Node_Info* pNodeInfo=new Tree_Node_Info{rowId,parentId,pItem,rowData};
                m_TreeNodeInfo.insert(rowId,pNodeInfo);
                setNodeIconType(rowId,iconType);
            }
            pItem->setText(rowData[i].toString());
        }
        else
        {
            m_TreeNodeInfo.value(rowId)->nodeDatas.append(QVariant());
        }
        rowItems<<pItem;
    }
    //判定顶层节点是否存在
    if(m_TreeNodeInfo.contains(parentId))
    {
        m_TreeNodeInfo.value(parentId)->pNodeItem->appendRow(rowItems);
    }
    else //若不存在，则直接在根结点后添加一行数据
    {
        m_pModel->appendRow(rowItems);
    }
    return true;
}

/**
 * @brief insterRowData 插入行数据
 * @param rowId 行id
 * @param rowData 添加的行数据
 * @param index 引索第几个
 * @param parentId 父级Id
 * @param iconType 设置图标类型
 * @return 返回插入行数据是否成功
 */
bool GY_TreeView::insterRowData(const QVariant &rowId, const QVector<QVariant> &rowData, const int index, const QVariant &parentId, const QVariant iconType)
{
    if(m_TreeNodeInfo.contains(rowId)||!rowData.size()||!m_pModel||!m_pModel->columnCount())
    {
        return false;
    }
    QList<QStandardItem*> rowItems;
    for(int i=0;i<m_pModel->columnCount();i++)
    {
        QStandardItem* pItem=new QStandardItem;
        if(i<rowData.size())
        {
            pItem->setData(rowData[i]);
            pItem->setText(rowData[i].toString());
            //对每行第一列数据设置id和子节点
            if(i==0)
            {
                pItem->setData(rowId,Qt::UserRole);
                Tree_Node_Info* pNodeInfo=new Tree_Node_Info{rowId,parentId,pItem,rowData};
                m_TreeNodeInfo.insert(rowId,pNodeInfo);
                setNodeIconType(rowId,iconType);
            }
        }
        else
        {
            m_TreeNodeInfo.value(rowId)->nodeDatas.append(QVariant());
        }

        rowItems<<pItem;
    }
    //判定顶层节点是否存在
    if(m_TreeNodeInfo.contains(parentId))
    {
        QStandardItem* pItem = m_TreeNodeInfo.value(parentId)->pNodeItem;
        if(index<pItem->rowCount()){
            pItem->insertRow(index,rowItems);
        }
        else
        {
            pItem->appendRow(rowItems);
        }
    }
    else //若不存在，则直接在根结点后在对应索引处插入一行数据
    {
        if(index<m_pModel->rowCount()){
            m_pModel->insertRow(index,rowItems);
        }
        else
        {
            m_pModel->appendRow(rowItems);
        }
    }
    return  true;
}

/**
 * @brief deleteRow  删除指定行
 * @param id 删除行的id号
 * @return 返回删除是否成功
 */
bool GY_TreeView::deleteRow(const QVariant &rowId)
{
    if(!m_TreeNodeInfo.contains(rowId))
    {
        return false;
    }
    QStandardItem* pItem = m_TreeNodeInfo.value(rowId)->pNodeItem;
    //判定是否是顶层节点
    if(!pItem->parent())
    {
        m_pModel->removeRow(pItem->index().row());
    }
    else
    {
        pItem->parent()->removeRow(pItem->index().row());
    }
    m_TreeNodeInfo.remove(rowId);

    return true;
}

/**
 * @brief clearData 清除所有数据
 */
void GY_TreeView::clearData()
{
    m_pModel->clear();
    m_TreeNodeInfo.clear();
}

/**
 * @brief setRowData  修改行数据
 * @param rowId  修改行id
 * @param rowData  要修改的数据
 * @return 是否修改成功
 */
bool GY_TreeView::setRowData(const QVariant &rowId, const QVector<QVariant> &rowData)
{
    if(!m_TreeNodeInfo.contains(rowId))
    {
        return false;
    }

    QStandardItem* pNodeItem = m_TreeNodeInfo.value(rowId)->pNodeItem;
    QStandardItem* pParentItem = new QStandardItem;
    QVariant nodeParentId;
    if(pNodeItem->parent()){ //判断是否有父节点
        pParentItem = pNodeItem->parent();
        nodeParentId = m_TreeNodeInfo.value(rowId)->nodeParentId; //记录父节点
    }
    else{
        pParentItem = m_pModel->invisibleRootItem();
    }

    QList<QStandardItem*> rowItems;
    for(int j=0;j<m_pModel->columnCount();j++)
    {
        QStandardItem* pNewRowItem = pParentItem->child(pNodeItem->index().row(),j);
        if(j<rowData.size())
        {
            pNewRowItem->setData(rowData.at(j));
            pNewRowItem->setText(rowData.at(j).toString()); //后期添加按键，则不能用text格式，需判断一下
            if(j==0)
            {
                pNewRowItem->setData(rowData.at(j),Qt::UserRole);
                Tree_Node_Info* pNodeInfo=new Tree_Node_Info{rowId,nodeParentId,pNewRowItem,rowData}; //存入新节点
                m_TreeNodeInfo.insert(rowId,pNodeInfo);
                pNewRowItem->setIcon(m_IconIdMap.value(rowId));
            }
        }
        else
        {
            pNewRowItem->setData(QVariant());
            pNewRowItem->setText(QVariant().toString());
        }
        rowItems<<pNewRowItem;
    }
    return true;
}

/**
 * @brief setCellData  修改单元格数据
 * @param id  修改的行id
 * @param columnIndex  修改第几列
 * @param cellData  要修改的数据
 * @return 是否修改成功
 */
bool GY_TreeView::setCellData(const QVariant &id, const int columnIndex, const QVariant &cellData)
{
    if(!m_TreeNodeInfo.contains(id) || columnIndex<0 || columnIndex>=m_pModel->columnCount())
    {
        return false;
    }
    QStandardItem* pNodeItem = m_TreeNodeInfo.value(id)->pNodeItem;
    QStandardItem* pParentItem = new QStandardItem;
    QVariant nodeParentId;
    if(pNodeItem->parent()){
        pParentItem = pNodeItem->parent();
        nodeParentId = m_TreeNodeInfo.value(id)->nodeParentId;
    }
    else{
        pParentItem = m_pModel->invisibleRootItem();
    }

    QStandardItem *pNewNodeItem = pParentItem->child(pNodeItem->index().row(),columnIndex);
    pNewNodeItem->setData(cellData);
    pNewNodeItem->setText(cellData.toString());
    QVector<QVariant> rowData;
    for(int i=0;i< m_TreeNodeInfo.value(id)->nodeDatas.size();i++)
    {
        QVariant newData = m_TreeNodeInfo.value(id)->nodeDatas.at(i);
        if(i==columnIndex)
        {
            newData = cellData;
        }
        rowData<<newData;

        if(i==0)
        {
            pNewNodeItem->setData(cellData,Qt::UserRole);
            pNewNodeItem->setIcon(m_IconIdMap.value(id));
        }
    }

    m_TreeNodeInfo.remove(id); //移出原来的节点
    Tree_Node_Info* pNodeInfo=new Tree_Node_Info{id,nodeParentId,pNewNodeItem,rowData}; //存入新节点
    m_TreeNodeInfo.insert(id,pNodeInfo);
    return  true;
}

/**
 * @brief getRowData  通过id获取行数据
 * @param id  要获取的节点id
 * @return id对应的行数据
 */
QVector<QVariant> GY_TreeView::getRowData(const QVariant &id)
{
    QVector<QVariant> rowData = QVector<QVariant>()<<"错误";
    if(!m_TreeNodeInfo.contains(id))
    {
        return rowData;
    }
    rowData = m_TreeNodeInfo.value(id)->nodeDatas;
    return rowData;
}

/**
 * @brief getRowData  通过parentId获取行数据
 * @param index  引索要获取第几行
 * @param parentId  父节点id
 * @return 索引的行数据
 */
QVector<QVariant> GY_TreeView::getRowDatas(const int index, const QVariant &parentId)
{
    QVector<QVariant> rowData = QVector<QVariant>()<<"错误";
    if(!m_TreeNodeInfo.contains(parentId) ||index<0 ||index>m_TreeNodeInfo.value(parentId)->pNodeItem->rowCount())
    {
        return rowData;
    }
    QStandardItem* pParentItem = m_TreeNodeInfo.value(parentId)->pNodeItem;
    rowData.clear();
    for(int i=0;i<m_pModel->columnCount();i++)
    {
        rowData << pParentItem->child(index,i)->data();
    }
    return rowData;
}

/**
 * @brief getCellData  获取单元格数据
 * @param id  节点id
 * @param columnIndex  索引第几列
 * @param data  单元格的数据
 * @return 返回是否获取成功
 */
bool GY_TreeView::getCellData(const QVariant &id, const int columnIndex, QVariant &data)
{
    if(!m_TreeNodeInfo.contains(id) || columnIndex<0 || columnIndex>=m_pModel->columnCount())
    {
        return false;
    }
    data = m_TreeNodeInfo.value(id)->nodeDatas.at(columnIndex);
    return true;
}

/**
 * @brief addIconType 添加图标类型
 * @param iconType 图标类型
 * @param icon 图标
 * @return 是否添加成功
 */
bool GY_TreeView::addIconType(const QVariant &iconType, const QIcon &icon)
{
    if(m_IconTypeMap.contains(iconType)) //如果图标类型存在
    {
        return false;
    }
    m_IconTypeMap.insert(iconType,icon); //记录图标和类型的关联信息
    return true;
}

/**
 * @brief setNodeIconType 设置id对应的图标
 * @param id 行id
 * @param iconType 图标类型
 * @return 是否设置成功
 */
bool GY_TreeView::setNodeIconType(const QVariant &id, const QVariant &iconType)
{
    if(!m_TreeNodeInfo.contains(id) || !m_IconTypeMap.contains(iconType)) //如果行id或者图标类型不存在
    {
        return false;
    }
    QStandardItem* pItem = m_TreeNodeInfo.value(id)->pNodeItem;
    QIcon icon = m_IconTypeMap.value(iconType); // 获取类型对应的图标
    m_IconIdMap.insert(id,icon); //记录图标和id的关联信息
    pItem->setIcon(icon);
    return true;
}

/**
 * @brief getSelecRowId  获取选择行id
 * @return  多选下返回选中的第一行
 */
QVariant GY_TreeView::getSelectRowId()
{
    return m_selectRowId;
}

/**
 * @brief getSelectRowIds 获取选择行id
 * @return  单选时返回一个id
 */
QVector<QVariant> GY_TreeView::getSelectRowIds()
{
    return  m_getselectRowIdsVec;
}

/**
 * @brief setRowSelectState 设置行选择状态
 * @param rowId 节点ID
 * @param isSelect 该行是否选择
 * @return 是否设置成功
 */
bool GY_TreeView::setRowSelectState(const QVariant &rowId, const bool isSelect)
{
    if(!m_TreeNodeInfo.contains(rowId) || !isSelect)
    {
        return false;
    }
    QStandardItem* pItem = m_TreeNodeInfo.value(rowId)->pNodeItem;
    if(pItem->isSelectable())
    {
        pItem->setSelectable(isSelect);
        return true;
    }
    return false;
}

/**
 * @brief setRowExpendState  设置行展开模式
 * @param rowId  第几个id
 * @param isExpend  是否展开
 * @return 返回是否展开该行
 */
bool GY_TreeView::setRowExpendState(QVariant rowId, bool isExpend)
{
    if(!m_TreeNodeInfo.contains(rowId) || !isExpend || !m_pModel)
    {
        return false;
    }
    QStandardItem* pItem = m_TreeNodeInfo.value(rowId)->pNodeItem;
    treeAllChildExpend(pItem,isExpend); //展开该id所有子节点
    treeTopPareentExpent(pItem,isExpend); //递归展开该id父节点
    return true;
}

/**
 * @brief treeAllChildExpend 所有子节点展开
 * @param pItem 子节点的item
 * @param isExpend 是否展开
 */
void GY_TreeView::treeAllChildExpend(QStandardItem *pItem, bool isExpend)
{
    if(nullptr==pItem || !isExpend) //判断item是否存在，或者是否展开
    {
        return;
    }
    QModelIndex index = pItem->index();
    this->expand(index); //展开该item
    for(int i=0;i<pItem->rowCount();i++)
    {
        QStandardItem* pNewItem = pItem->child(i);
        treeAllChildExpend(pNewItem,isExpend);
    }
}

void GY_TreeView::treeTopPareentExpent(QStandardItem *pItem, bool isExpend)
{
    if(nullptr==pItem || !isExpend)
    {
        return;
    }
    QModelIndex index = pItem->index();
    this->expand(index);
    if(pItem->parent()) //判断父节点是否存在
    {
        treeTopPareentExpent(pItem->parent(),isExpend); //递归查找至最顶层父节点
    }
}

/**
 * @brief setIsChecked  设置是否显示复选框
 * @param isChecked  是否勾选
 */
void GY_TreeView::setIsChecked(const bool isChecked)
{
    m_isCheckable = isChecked;
    if(m_isCheckable)
    {
        for(int i=0;i<m_pModel->rowCount();i++)
        {
            QStandardItem* pItem = m_pModel->item(i);
            pItem->setCheckable(isChecked);
            if(pItem->hasChildren())
            {
                pItem->setTristate(isChecked);
                getAllChildChecked(pItem,isChecked); //设置所有节点的选择状态
            }
        }
    }
}

/**
 * @brief getAllChildChecked 设置所有节点的选择状态
 * @param pItem 子节点是item
 */
void GY_TreeView::getAllChildChecked(QStandardItem * const pItem, const bool isChecked)
{
    if(nullptr==pItem)
    {
        return;
    }
    for(int i=0;i<pItem->rowCount();i++)
    {
        QStandardItem* pNewItem = pItem->child(i); //获取子节点item
        pNewItem->setCheckable(isChecked);
        if(pNewItem->hasChildren())
        {
            pNewItem->setTristate(isChecked);
            getAllChildChecked(pNewItem,isChecked); //递归遍历所有节点
        }
    }
}

/**
 * @brief getIsChecked 获取当前是否显示复选框
 * @return 返回是否显示复选框
 */
bool GY_TreeView::getIsChecked()
{
    return m_isCheckable;
}

/**
 * @brief getCheckedRowIds  获取选中的行id
 * @return 返回全部id
 */
QVector<QVariant> GY_TreeView::getCheckedRowIds()
{
    return m_checkedRowIds;
}

/**
 * @brief getCheckRowDatas  获取选中行数据
 * @return
 */
QMap<QVariant, QVector<QVariant> > GY_TreeView::getCheckRowDatas()
{
    return m_checkRowDatas;
}

/**
 * @brief setRowCheckState  设置复选框选中行状态
 * @param rowId  节点id
 * @param isCheck  是否选中
 * @return 返回该行是否被选中，true选中，false未被选中
 */
bool GY_TreeView::setRowCheckState(const QVariant &rowId, const bool isCheck)
{
    if(!m_TreeNodeInfo.contains(rowId) || !isCheck)
    {
        return false;
    }
    QStandardItem* pItem = m_TreeNodeInfo.value(rowId)->pNodeItem; //找出id对应的item
    if(pItem->isCheckable())
    {
        pItem->setCheckState(isCheck?Qt::Checked: Qt::Unchecked);
        setTreeAllChildChecked(pItem,isCheck); //设置子节点全选/全不选
        return true;
    }
    return false;
}

/**
 * @brief treeAllChecked  复选框全选/全不选
 * @param ischeck 是否勾选
 */
void GY_TreeView::setTreeAllChecked(bool isCheck)
{
    if( !m_pModel ){ //如果列表为空
        return;
    }
    //遍历map
    foreach (Tree_Node_Info* pTreeInfo, m_TreeNodeInfo) {
        pTreeInfo->pNodeItem->setCheckState(isCheck?Qt::Checked: Qt::Unchecked);//设置item勾选状态
        if(pTreeInfo->pNodeItem->checkState()==Qt::Checked) //如果item勾选，记录id和data
        {
            m_checkedRowIds.append(pTreeInfo->nodeId);
            m_checkRowDatas.insert(pTreeInfo->nodeId,pTreeInfo->nodeDatas);
        }
        else //清除记录
        {
            m_checkedRowIds.clear();
            m_checkRowDatas.clear();
        }
    }
}

/**
 * @brief setTreeAllChildChecked  子节点全选/全不选
 * @param pItem 对应的item
 * @param check 是否勾选
 */
void GY_TreeView::setTreeAllChildChecked(QStandardItem *pItem, bool check)
{
    if(nullptr==pItem)
    {
        return;
    }
    for(int i=0;i<pItem->rowCount();i++) //递归遍历子节点勾选状态
    {
        QStandardItem* pNewItem = pItem->child(i);
        setTreeAllChildChecked(pNewItem,check);
    }
    if(pItem->isCheckable())
    {
        pItem->setCheckState(check?Qt::Checked: Qt::Unchecked);//设置item勾选状态
        QVariant id = itemFindId(pItem);
        if(pItem->checkState()==Qt::Checked)//如果item勾选，记录id和data
        {
            m_checkedId = id;
            m_checkedRowIds.append(id);
            m_checkRowDatas.insert(id,m_TreeNodeInfo.value(id)->nodeDatas);
        }
        else
        {
            m_checkedRowIds.removeAll(id);
            m_checkRowDatas.remove(id);
        }
    }
}

/**
 * @brief treeCheckChildChanged  根据子节点改变，更改父节点
 * @param pItem 对应的item
 */
void GY_TreeView::treeCheckChildChanged(QStandardItem *pItem)
{
    if(nullptr==pItem)
    {
        return;
    }
    QVariant id = itemFindId(pItem);
    if(pItem->checkState()==Qt::Checked)
    {
        m_checkedId = id;
        m_checkedRowIds.append(id);
        m_checkRowDatas.insert(id,m_TreeNodeInfo.value(id)->nodeDatas);
    }
    else
    {
        m_checkedRowIds.removeOne(id);
        m_checkRowDatas.remove(id);
    }
    Qt::CheckState siblingState = checkSibling(pItem); //检测item兄弟节点情况
    QStandardItem* pParentItem = pItem->parent(); //获取父节点
    if(nullptr==pParentItem)
    {
        return;
    }
    if(Qt::PartiallyChecked==siblingState) //如果兄弟节点是半勾选
    {
        if(pParentItem->isCheckable() && pParentItem->isTristate())//判断父节点是否可勾选，且是三态
        {
            pParentItem->setCheckState(Qt::PartiallyChecked);
        }
    }
    else if(Qt::Checked==siblingState) //如果兄弟节点是全选
    {
        if(pParentItem->isCheckable())
        {
            pParentItem->setCheckState(Qt::Checked);
        }
    }
    else //如果兄弟节点没有勾选
    {
        if(pParentItem->isCheckable())
        {
            pParentItem->setCheckState(Qt::Unchecked);
        }
    }
    treeCheckChildChanged(pParentItem);
}

/**
 * @brief checkSibling  检测兄弟节点情况
 * @param pItem 对应的item
 * @return 返回勾选状态
 */
Qt::CheckState GY_TreeView::checkSibling(QStandardItem *pItem)
{
    QStandardItem* pParentItem = pItem->parent();
    if(nullptr==pParentItem)
    {
        return pItem->checkState();
    }
    int checkCount(0),unCheckCount(0);
    Qt::CheckState state;
    for(int i=0;i<pParentItem->rowCount();i++)
    {
        QStandardItem* pSiblingItem = pParentItem->child(i);
        state = pSiblingItem->checkState();
        if(Qt::PartiallyChecked==state)
        {
            return Qt::PartiallyChecked;
        }
        else if(Qt::Unchecked==state)
        {
            ++unCheckCount;
        }
        else
        {
            ++checkCount;
        }
        if(checkCount>0 && unCheckCount>0)
        {
            return Qt::PartiallyChecked;
        }
    }
    if(unCheckCount>0)
    {
        return Qt::Unchecked;
    }
    return Qt::Checked;
}

/**
 * @brief itemFindId 根据item查找对应的id
 * @param pItem 对应的item
 * @return 返回item对应的id
 */
QVariant GY_TreeView::itemFindId(QStandardItem *pItem)
{
    QVariant id;
    foreach (Tree_Node_Info* tableInfoIter, m_TreeNodeInfo) {
        if(tableInfoIter->pNodeItem==pItem){
            id = tableInfoIter->nodeId;
        }
    }
    return id;
}

/**
 * @brief mousePressEvent 鼠标单击空白事件
 * @param event 点击事件
 */
void GY_TreeView::mousePressEvent(QMouseEvent *event)
{
    QModelIndex index = this->indexAt(event->pos());
    if(!index.isValid())
    {
        m_getselectRowIdsVec.clear();
        setCurrentIndex(index); //实现空白处取消选择
    }
    else {
        QTreeView::mousePressEvent(event);
    }
}

/**
 * @brief receiveClicked 单击接收事件
 * @param index 当前index
 */
void GY_TreeView::receiveClicked(const QModelIndex &index)
{
    QStandardItem* pItem = m_pModel->itemFromIndex(index); //获得当前点击的item
    int row = index.row();

    if(pItem->parent())
    {
        pItem = pItem->parent()->child(row,0);
        m_selectRowId = itemFindId(pItem);
        QVariant parentId = m_TreeNodeInfo.value(m_selectRowId)->nodeParentId;
        emit selectChangeEvent(row,parentId); //发送选择改变信号
    }
    else
    {
        pItem = m_pModel->item(row,0);
        m_selectRowId = itemFindId(pItem);
    }
    emit selectChangeEvent(m_selectRowId);

    if(pItem->isCheckable()) //如果item是可勾选的
    {
        Qt::CheckState state = pItem->checkState();
        if(pItem->isTristate()) //判断是否是三态
        {
            if(state!=Qt::PartiallyChecked)
            {
                setTreeAllChildChecked(pItem,state==Qt::Checked?true:false);
            }
        }
        else
        {
            treeCheckChildChanged(pItem);
        }
        if(m_checkedId.isValid())
        {
            emit checkStateChangeEvent(m_selectRowId);
            m_checkedId.clear();
        }
    }

    for(int i=0;i<m_getselectRowIdsVec.size();i++)
    {
        if(m_getselectRowIdsVec.at(i)==m_selectRowId)
        {
            m_getselectRowIdsVec.removeOne(m_selectRowId);
            return;
        }
    }
    m_getselectRowIdsVec<<m_selectRowId;
}
